﻿using System;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace TSharp.Core.Aop
{
	/// <summary>
	/// 拦截器扩展 为每一个配置文件中注册的类型配置默认的拦截器
	/// 
	/// <para>by tangjingbo at 2009-10-27 17:22</para>
	/// </summary>
	public class DefaultInterceptorInterceptionExtension : Interception
	{
		private static readonly IInterceptor[] interceptors;

		static DefaultInterceptorInterceptionExtension()
		{
			interceptors = (from interceptorType in
			                	(from type in typeof (IInterceptor).Assembly.GetExportedTypes()
			                	 where typeof (IInterceptor).IsAssignableFrom(type) &&
			                	       type.IsAbstract == false &&
			                	       type.IsInterface == false
			                	 select type)
			                select Activator.CreateInstance(interceptorType) as IInterceptor).ToArray();
		}

		/// <summary>
		/// Initial the container with this extension's functionality.
		/// </summary>
		protected override void Initialize()
		{
			base.Initialize();
			IConfigurationSource configSource = ConfigurationSourceFactory.Create();
			var section = configSource.GetSection(PolicyInjectionSettings.SectionName) as PolicyInjectionSettings;
			if (section != null)
			{ 
                //section.ConfigureContainer(Container, configSource);
                section.ConfigureContainer(Container);
			}
			Context.Registering +=
			    (sender, e) => setInterceptorFor(e.TypeFrom, e.TypeTo, e.Name);
			Context.RegisteringInstance +=
			    (sender, e) => setInterceptorFor(e.RegisteredType, e.Instance.GetType(), e.Name)
			    ;
		}

		private void setInterceptorFor(Type typeToIntercept, Type typeOfInstance, String name)
		{
			foreach (IInterceptor interceptor in interceptors)
			{
				if (interceptor.CanIntercept(typeToIntercept) &&
				    (interceptor.GetInterceptableMethods(typeToIntercept, typeOfInstance).Count() != 0))
				{
					if (interceptor is IInstanceInterceptor)
					{
						Container.Configure<Interception>().SetDefaultInterceptorFor(typeToIntercept,
						                                                             interceptor as IInstanceInterceptor);
					}
					else if (interceptor is ITypeInterceptor)
					{
						Container.Configure<Interception>().SetDefaultInterceptorFor(typeToIntercept,
						                                                             interceptor as ITypeInterceptor);
					}
					break;
				}
			}
		}
	}
}